// copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
// see COPYRIGHT for reuse legalities
//


#import "WWLightInspectorShape.h"

@implementation WWLightInspectorShape

+ initialize { return [WWLightInspectorShape setVersion:1], self; }

- setBoundingBox:(RtBound)aBBox
{
  boundingBox[0] = aBBox[0];
  boundingBox[1] = aBBox[1];
  boundingBox[2] = aBBox[2];
  boundingBox[3] = aBBox[3];
  boundingBox[4] = aBBox[4];
  boundingBox[5] = aBBox[5];
  [self synchUpWithBoundingBox];

  return self;
}

- synchUpWithBoundingBox
{
  xMin = boundingBox[0];
  xMax = boundingBox[1];
  yMin = boundingBox[2];
  yMax = boundingBox[3];
  zMin = boundingBox[4];
  zMax = boundingBox[5];

  boxPoints[0][0] = xMin; 
  boxPoints[0][1] = yMin; 
  boxPoints[0][2] = zMin; 

  boxPoints[1][0] = xMax; 
  boxPoints[1][1] = yMin; 
  boxPoints[1][2] = zMin; 

  boxPoints[2][0] = xMax; 
  boxPoints[2][1] = yMax; 
  boxPoints[2][2] = zMin; 

  boxPoints[3][0] = xMin; 
  boxPoints[3][1] = yMax; 
  boxPoints[3][2] = zMin; 

  boxPoints[4][0] = xMin; 
  boxPoints[4][1] = yMin; 
  boxPoints[4][2] = zMax; 

  boxPoints[5][0] = xMax; 
  boxPoints[5][1] = yMin; 
  boxPoints[5][2] = zMax; 

  boxPoints[6][0] = xMax; 
  boxPoints[6][1] = yMax; 
  boxPoints[6][2] = zMax; 

  boxPoints[7][0] = xMin; 
  boxPoints[7][1] = yMax; 
  boxPoints[7][2] = zMax; 

  ////////////////////////////////////
  ////////// X Axis //////////////////
  ////////////////////////////////////
  // 1st point
  xAxisPoints[0][0] = 0.0;
  xAxisPoints[0][1] = 2.0*yMin;
  xAxisPoints[0][2] = 2.0*zMin;
  //if (yMin < 0.0) { xAxisPoints[0][1] = 2.0*yMin; } else { xAxisPoints[0][1] = yMin/2.0; }
  //if (zMin < 0.0) { xAxisPoints[0][2] = 2.0*zMin; } else { xAxisPoints[0][2] = zMin/2.0; }
  // 2nd point
  xAxisPoints[1][0] = 0.0;
  xAxisPoints[1][1] = 2.0*yMax;
  xAxisPoints[1][2] = 2.0*zMin;
  //if (yMax < 0.0) { xAxisPoints[0][1] = 2.0*yMax; } else { xAxisPoints[1][1] = yMax/2.0; }
  //if (zMin < 0.0) { xAxisPoints[0][2] = 2.0*zMin; } else { xAxisPoints[1][2] = zMin/2.0; }
  // 3rd point
  xAxisPoints[2][0] = 0.0;
  xAxisPoints[2][1] = 2.0*yMax;
  xAxisPoints[2][2] = 2.0*zMax;
  //if (yMax < 0.0) { xAxisPoints[0][1] = 2.0*yMax; } else { xAxisPoints[2][1] = yMax/2.0; }
  //if (zMax < 0.0) { xAxisPoints[0][2] = 2.0*zMax; } else { xAxisPoints[2][2] = zMax/2.0; }
  // 4th point
  xAxisPoints[3][0] = 0.0;
  xAxisPoints[3][1] = 2.0*yMin;
  xAxisPoints[3][2] = 2.0*zMax;
  //if (yMin < 0.0) { xAxisPoints[0][1] = 2.0*yMin; } else { xAxisPoints[3][1] = yMin/2.0; }
  //if (zMax < 0.0) { xAxisPoints[0][2] = 2.0*zMax; } else { xAxisPoints[3][2] = zMax/2.0; }

  ////////////////////////////////////
  ////////// Y Axis //////////////////
  ////////////////////////////////////
  // 1st point
  yAxisPoints[0][0] = 2.0*xMin;
  yAxisPoints[0][1] = 0.0;
  yAxisPoints[0][2] = 2.0*zMin;
  //if (xMin < 0.0) { yAxisPoints[0][0] = 2.0*xMin; } else { yAxisPoints[0][0] = xMin/2.0; }
  //if (zMin < 0.0) { yAxisPoints[0][2] = 2.0*zMin; } else { yAxisPoints[0][2] = zMin/2.0; }
  // 2nd point
  yAxisPoints[1][0] = 2.0*xMax;
  yAxisPoints[1][1] = 0.0;
  yAxisPoints[1][2] = 2.0*zMin;
  //if (xMax < 0.0) { yAxisPoints[0][0] = 2.0*xMax; } else { yAxisPoints[1][0] = xMax/2.0; }
  //if (zMin < 0.0) { yAxisPoints[0][2] = 2.0*zMin; } else { yAxisPoints[1][2] = zMin/2.0; }
  // 3rd point
  yAxisPoints[2][0] = 2.0*xMax;
  yAxisPoints[2][1] = 0.0;
  yAxisPoints[2][2] = 2.0*zMax;
  //if (xMax < 0.0) { yAxisPoints[0][0] = 2.0*xMax; } else { yAxisPoints[2][0] = xMax/2.0; }
  //if (zMax < 0.0) { yAxisPoints[0][2] = 2.0*zMax; } else { yAxisPoints[2][2] = zMax/2.0; }
  // 4th point
  yAxisPoints[3][0] = 2.0*xMin;
  yAxisPoints[3][1] = 0.0;
  yAxisPoints[3][2] = 2.0*zMax;
  //if (xMin < 0.0) { yAxisPoints[0][0] = 2.0*xMin; } else { yAxisPoints[3][0] = xMin/2.0; }
  //if (zMax < 0.0) { yAxisPoints[0][2] = 2.0*zMax; } else { yAxisPoints[3][2] = zMax/2.0; }

  ////////////////////////////////////
  ////////// Z Axis //////////////////
  ////////////////////////////////////
  // 1st point
  //if (xMin < 0.0) { zAxisPoints[0][0] = 2.0*xMin; } else { zAxisPoints[0][0] = xMin/2.0; }
  //if (yMin < 0.0) { zAxisPoints[0][1] = 2.0*yMin; } else { zAxisPoints[0][1] = yMin/2.0; }
  zAxisPoints[0][0] = 2.0*xMin;
  zAxisPoints[0][1] = 2.0*yMin;
  zAxisPoints[0][2] = 0.0;
  // 2nd point
  //if (xMin < 0.0) { zAxisPoints[0][0] = 2.0*xMin; } else { zAxisPoints[1][0] = xMin/2.0; }
  //if (yMax < 0.0) { zAxisPoints[0][1] = 2.0*yMax; } else { zAxisPoints[1][1] = yMax/2.0; }
  zAxisPoints[1][0] = 2.0*xMin;
  zAxisPoints[1][1] = 2.0*yMax;
  zAxisPoints[1][2] = 0.0;
  // 3rd point
  //if (xMax < 0.0) { zAxisPoints[0][0] = 2.0*xMax; } else { zAxisPoints[2][0] = xMax/2.0; }
  //if (yMax < 0.0) { zAxisPoints[0][1] = 2.0*yMax; } else { zAxisPoints[2][1] = yMax/2.0; }
  zAxisPoints[2][0] = 2.0*xMax;
  zAxisPoints[2][1] = 2.0*yMax;
  zAxisPoints[2][2] = 0.0;
  // 4th point
  //if (xMax < 0.0) { zAxisPoints[0][0] = 2.0*xMax; } else { zAxisPoints[3][0] = xMax/2.0; }
  //if (yMin < 0.0) { zAxisPoints[0][1] = 2.0*yMin; } else { zAxisPoints[3][1] = yMin/2.0; }
  zAxisPoints[3][0] = 2.0*xMax;
  zAxisPoints[3][1] = 2.0*yMin;
  zAxisPoints[3][2] = 0.0;

  return self;
}

- init
{
  RtBound  aBoundingBox = { -1., 1., -1., 1., -1., 1. }; 

  [super init];

  boxNVertices[0] = boxNVertices[1] = boxNVertices[2] = boxNVertices[3] = boxNVertices[4] = boxNVertices[5] = 4;

  boxVertices[0] = 0;
  boxVertices[1] = 1;
  boxVertices[2] = 2;
  boxVertices[3] = 3;

  boxVertices[4] = 1;
  boxVertices[5] = 5;
  boxVertices[6] = 6;
  boxVertices[7] = 2;

  boxVertices[8] = 5;
  boxVertices[9] = 6;
  boxVertices[10] = 7;
  boxVertices[11] = 4;

  boxVertices[12] = 0;
  boxVertices[13] = 3;
  boxVertices[14] = 7;
  boxVertices[15] = 4;

  boxVertices[16] = 3;
  boxVertices[17] = 2;
  boxVertices[18] = 6;
  boxVertices[19] = 7;

  boxVertices[20] = 0;
  boxVertices[21] = 1;
  boxVertices[22] = 5;
  boxVertices[23] = 4;

  [self setBoundingBox:aBoundingBox];

  return self;
}



#define X_AXIS 1.0, 0.0, 0.0
#define Y_AXIS 0.0, 1.0, 0.0
#define Z_AXIS 0.0, 0.0, 1.0
#define	wwMax(a,b)  (((a)>(b))?(a):(b))
#define	wwMin(a,b)  (((a)>(b))?(b):(a))

// it's probably worth caching all this info...
//
- renderSelf:(N3DCamera *)camera
{
  // red:   255 81 107 == 1.00  .318 .420 
  // green: 96 215 121 ==  .376 .843 .475
  // blue:  98 124 255 ==  .384 .486 1.00
  RtColor  xColor = { 1.00 ,  .318,  .420 },
           yColor = {  .376,  .843,  .475 },
           zColor = {  .384,  .486, 1.00  };
  RtFloat  xSize, ySize, zSize;


  [super renderSelf:camera];

  // draw the inside box
  RiPointsPolygons(6, boxNVertices, boxVertices, RI_P, boxPoints, RI_NULL);

  // draw the xAxis (the yzPlane)
  RiColor(xColor);
  RiPolygon(4, RI_P, xAxisPoints, RI_NULL);

  // draw the yAxis (the xzPlane)
  RiColor(yColor);
  RiPolygon(4, RI_P, yAxisPoints, RI_NULL);

  // draw the zAxis (the xyPlane)
  RiColor(zColor);
  RiPolygon(4, RI_P, zAxisPoints, RI_NULL);
  // want small cone at zMax
  zSize = zMax - zMin;
  RiTranslate(0, 0, (2*zMax));
  RiCone((.3 * zSize), (.1 * zSize), 360, RI_NULL);
  RiTranslate(0, 0, (-2*zMax));

  RiRotate(-90, X_AXIS);
  // rotate about X -90 degrees to be pointing along the Y axis
  RiColor(yColor);
  ySize = yMax - yMin;
  RiTranslate(0, 0, (2*yMax));
  RiCone((.3 * ySize), (.1 * ySize), 360, RI_NULL);
  RiTranslate(0, 0, (-2*yMax));

  // rotate about Y 90 degrees to be pointing along the X axis
  RiRotate(90, Y_AXIS);
  RiColor(xColor);
  xSize = xMax - xMin;
  RiTranslate(0, 0, (2*xMax));
  RiCone((.3 * xSize), (.1 * xSize), 360, RI_NULL);
  RiTranslate(0, 0, (-2*xMax));


  return self;
}


@end
